#ifndef TRAFFIC_JAM_HELPERS_HPP
#define TRAFFIC_JAM_HELPERS_HPP

#include <pthread.h>
#include "direction.hpp"

#define _ID_CONCAT(x, y) x ## y
#define ID_CONCAT(x, y) _ID_CONCAT(x, y)

namespace jam {

/* ========
 * 构造方向(位)相关的四元组
 * ======== */

/* 构造各项同性的类型构造子 */
template<typename Type>
struct id_type_cons {
  template<direction_t>
  struct cons {
    typedef Type type;
  };
};

/* 构造各向异性的类型构造子 */
template<template<direction_t> class TypeTpl>
struct quad_type_cons {
  template<direction_t dir>
  struct cons {
    typedef TypeTpl<dir> type;
  };
};

// 宏 & 模板滥用预警 这里的一企鹅努力都是为了
// 1. 尽可能地控制代码里的冗余
// 2. 尽可能多得使用方向来表达逻辑
// 3. 保证1 & 2在可靠的现代编译器上能做到尽可能低的性能损失

/* 在(East, east), (South, south), (West, west), (North, north)上展开宏m */
#define ITERATE_COUPLE_ESWN(m) ITERATE_ESWN_ARG(m, east, south, west, north)

/* 原始四元组, 四个独立的字段(east, west, south, north)分别个和东南西北四个方向绑定 */
template<template<direction_t> class TypeCons>
struct _quadruple {
  template<direction_t dir>
  using FieldType = typename TypeCons<dir>::type;
  #define LAZY_FIELD(d, n) FieldType<d> n = FieldType<d>();
  ITERATE_COUPLE_ESWN(LAZY_FIELD);
};

/* 从绑定方向计算四元组的成员指针 */
template<typename _Quad, direction_t dir>
struct _selector { };

#define SELECTOR(d, f) \
template<typename _Quad> \
struct _selector<_Quad, d> { \
  constexpr static decltype(_Quad:: f) _Quad::* value = &_Quad:: f; \
}
ITERATE_COUPLE_ESWN(SELECTOR);

#undef LAZY_FIELD
#undef SELECTOR
#undef FIELD_EWSN

/* 综合四元组 */
template<template<direction_t> class TypeCons>
struct quadruple {
  /* 四元组类型 */
  struct type: _quadruple<TypeCons> { };
  /* 选择器模板 */
  template<direction_t dir>
  struct selector: _selector<type, dir> { };
};

/* 读写四元组的辅助宏 */
#define QUAD_FIELD(type, quad, direction) \
  (quad.*(type::selector<direction>::value))

#define QUADP_FIELD(type, quad, direction) \
  (quad->*(type::selector<direction>::value))

}
#endif //TRAFFIC_JAM_HELPERS_HPP
